package com.mail.config.database;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import com.mail.config.database.DataSourceConfiguration;

/**
 *Mybatis 配置类  （相当与原先的 Mybatis在 Spring 中的xml配置文件）
 *此处我们是在Spring Boot 只需要继承MybatisAutoConfiguration 
 *@AutoConfigureAfter 加载完DataSourceConfiguration 再加载该类，
 *
 */
@Configuration //Mybatis 配置类
@AutoConfigureAfter({DataSourceConfiguration.class}) //
public class MybatisConfiguration extends MybatisAutoConfiguration{
	//声明两个数据源，
	@Resource(name="masterDataSource")
	private DataSource masterDataSource;
	@Resource(name="slaveDataSource")
	private DataSource slaveDataSource;
	
	//在配置中创建一个bean SqlSessionFatory
	@Bean(name="sqlSessionFactory")
	public SqlSessionFactory sqlSessionFactory() throws Exception{
		/**
		 * 1.返回Spring Boot 中的sqlSessioFactory
		 * 2.到底使用主还是从数据源我们使用 Mybatis 提供的一个路由来动态的分配
		 * 3.AbstractRoutingDataSource 相当于一个代理， 由他来动态管理使用哪一个数据源
		 * 4.首先创建一个类来继承这个 Mybatis 提供的类AbstractRoutingDataSource
		 * 5.把新创建的数据源注入到sqlSessionFactory中
		 */
		return super.sqlSessionFactory(roundRobinDataSouceProxy());
									
	}
	/**
	 * 通过路由动态的获取使用那种数据源（动态	切换 ）
	 * 把两个数据源交由路由来管理，然后把数据源注入到 SqlSessionFactory 这个bean中去
	 * 如何让连个数据源和这个类来产生关联关系呢
	 */
	public AbstractRoutingDataSource roundRobinDataSouceProxy() {
		ReadWriteSplitRoutingDataSource proxy = new ReadWriteSplitRoutingDataSource();
		//此处也可以用你常见的HashMap
		/*SoftHashMap targetDataSources  = new ClassLoaderRepository.SoftHashMap();*/
		Map<Object,Object> targetDataSources = new HashMap<Object,Object>();
		targetDataSources.put(DataSourceContextHolder.DataBaseType.MASTER, masterDataSource);
		targetDataSources.put(DataSourceContextHolder.DataBaseType.SLAVE, slaveDataSource);
		//设置默认情况下执行的数据源
		proxy.setDefaultTargetDataSource(masterDataSource);
		proxy.setTargetDataSources(targetDataSources);//把主从数据源放入到map中，把这个map注入到建立的路由中，
		return proxy;
	}
}
